/****************************************************************
                     markerstuff.c
written by IL
seriously edited by CAS
Marker Text Box routines
*****************************************************************/
#include "fpp.h"
#include <float.h>
#include <gtk/gtk.h>

#define MAX_CTGMKR_ELEMS 15  /* WN 4/04 raised from 2 */

extern int Marker_clone_max; /* cari 14.5.4 defined in fpc_load */
extern GtkWidget *ctg_window;  /*fred 3/5/03*/
extern int currentmarker, centreMarker;
extern GtkWidget *markerEditWindow;
extern GtkWidget *create_markerEditWindow();
extern void addgel();
extern void formatdate();

void spooky2(int box, float x, float y);
void spooky3(int box, float x, float y);
int calcmarkerctgpos();
BOOL markerOrder(void *s, void *b);
void getmarkerdata2(int markerindex);
void updateproj(void);
void falsepick(int box, float x, float y);
void preserveit(int type);
void markercorrect(void);
void sortmarkers(void);
void highlightmarkernodraw(BOOL high);
void highlightnodraw();

/*******************************************************
                  quitMark
FIX 17mar99 - markers freed when next contig starts, which was
causeing problem on changing projects.
**********************************************************/
void quitMark()
{
  /*struct marker *tmp;*/
  struct markerlist *markerptr,*markerptrtemp;

  markerptr=markerlistroot;
  while(markerptr != NULL){
    markerptrtemp = markerptr;
    /*tmp = arrp(markerdata,markerptr->markerindex, MARKER);
    tmp->box = 0;
    tmp->colour = 0; WMN: can't do this since markers may have been deleted */
    markerptr = markerptr->next;
    messfree(markerptrtemp);
  }
  markerlistroot = NULL;

  
}
/*******************************************************/
void markersinctgcount()
{
  int i,j;
  struct markerctgpos *pos;
  BOOL found;

  for (i=1;i<=max_contig;i++)
    contigs[i].markers = 0;

  for(j=0;j<arrayMax(markerdata);j++){
    pos = arrp(markerdata,j,MARKER)->pos;
    found = FALSE;
    while(pos!= NULL){
      contigs[pos->ctg].markers++;
      pos= pos->next;
    }
  }
}

/*****************************************************************
             DEF: displaydetailsformkr
clonectgtype == TRUE if displaying clones
clonectgtype == FALSE if displaying contigs
*****************************************************************/
void displaydetailsformkr(int index, int clonectgtype)
{
   struct marker *marker;
   struct markerclone *clones;
   struct markerdisplist *another=NULL;
   char str1[140];
   float line = 1.0;
   int i, j=-1, num=1;
   BOOL first = TRUE;
   struct markerctgpos *p;
   static MENUOPT amenu[] = { 
	{ graphDestroy, "Close"},
    { 0, 0 } };

   if (index == -1) return;
   if (index >= arrayMax(markerdata)) return;
   if (graphActivate(gmarkerpopup)) {
      graphPop();
      displaymess("Marker popup open. Please close before opening a text window.");
      return;
   }
  if(graphActivate(gmarkerpopup)){
      graphClear();
      graphPop();
      graphRegister(PICK, spooky2);
  }
  else{
      gmarkerpopup = graphCreate (TEXT_SCROLL,"Marker",.2,.2,.26,.3) ;
      graphRegister(PICK, spooky3);
  }
  graphMenu(amenu);

  marker = arrp(markerdata, index, MARKER);
  sprintf(str1, "%s %s", markertype[marker->type], marker->marker);
  line += 1.0;
  graphText(str1, 1.0, line);

  line+=2.0;
  if (clonectgtype == TRUE)    // display clones
  {
     /* 1st CLONE */
     sprintf(str1,"Clones %d:",marker->count);
     graphText(str1,1.0,line);
     line+=1.0;

     i = graphBoxStart();
     j = graphTextFormat(BOLD);
     graphText(arrp(acedata,marker->cloneindex,CLONE)->clone,2.0,line);
     j = graphTextFormat(j);

     if(first){
       popupmarkerlist = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
       popupmarkerlist->cloneindex = marker->cloneindex;
       popupmarkerlist->high = 0;
       popupmarkerlist->box = i;
       popupmarkerlist->type = CLONECLASS;
       popupmarkerlist->next = NULL;
       another = popupmarkerlist;
       first = FALSE;
     }
     else{
       another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
       another = another->next;
       another->cloneindex = marker->cloneindex;
       another->high = 0;
       another->box = i;
       another->type = CLONECLASS;
       another->next = NULL;
     }
     if(arrp(acedata,marker->cloneindex,CLONE)->ctg != 0)
       graphText(arrp(acedata,marker->cloneindex,CLONE)->chctg,16.0,line);
     if (IsSeq(arrp(acedata,marker->cloneindex,CLONE)))
                graphText("S",25.0,line);
     if (marker->weak)
                graphText("Weak",27.0,line);
     graphBoxEnd();

     /* REST of CLONE */
     clones = marker->nextclone;
     while(clones != NULL){
       line += 1.0;
       i = graphBoxStart();
       if(!preserve)
         j = graphTextFormat(BOLD);
       graphText(arrp(acedata,clones->cloneindex,CLONE)->clone,2.0,line);
       if(!preserve)
         j = graphTextFormat(j);

       if(!preserve){
         another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
         another = another->next;
         another->cloneindex = clones->cloneindex;
         another->high = 0;
         another->box = i;
         another->type = CLONECLASS;
         another->next = NULL;
       }
       if(arrp(acedata,clones->cloneindex,CLONE)->ctg != 0)
         graphText(arrp(acedata,clones->cloneindex,CLONE)->chctg,16.0,line);
       graphBoxEnd();
       if(IsSeq(arrp(acedata,clones->cloneindex,CLONE)))
               graphText("S",25.0,line);
       if(clones->weak)
               graphText("Weak",27.0,line);
       clones = clones->nextclone;
     }
  }
  else // clonectgtype == FALSE    ==> display contigs
  {
     p = marker->pos;
     while(p!=NULL){
       if(p->ctg != 0){
         i = graphBoxStart();
         sprintf(str1," ctg%d ",p->ctg);
         j = graphTextFormat(BOLD);
         graphText(str1,1.0,line);
         j = graphTextFormat(j);

         clones = marker->nextclone;
         num=0;
         if(arrp(acedata,marker->cloneindex,CLONE)->ctg == p->ctg)
           num++;
         while(clones != NULL){
           if(arrp(acedata,clones->cloneindex,CLONE)->ctg == p->ctg)
             num++;
           clones = clones->nextclone;
         }

         sprintf(str1," %d %d",num,p->pos);
         num = 0;
         graphText(str1,10.0,line);
         graphBoxEnd();
         if(first){
           popupmarkerlist = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
           popupmarkerlist->cloneindex = p->ctg;
           popupmarkerlist->high = 0;
           popupmarkerlist->type = CTGCLASS;
           popupmarkerlist->box = i;
           popupmarkerlist->next = NULL;
           another = popupmarkerlist;
           first = FALSE;
         }
         else{
           another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
           another = another->next;
           another->cloneindex = p->ctg;
           another->high = 0;
           another->box = i;
           another->type = CTGCLASS;
           another->next = NULL;
         }
         line = line + 1.0;
       }
       p = p->next;
     }
  }

  graphTextBounds(3, line+5);

  graphRedraw();
}


/*******************************************************************
 called when a clone or contig is selcted from marker text box 
*******************************************************************/
void spooky2(int box, float x, float y)
{
  struct markerdisplist *another, *ptrlist;
  struct markerctgpos *ptr;
  BOOL found=FALSE,found2;

  if(box == 0) return;

  for(ptrlist=NULL, found=FALSE, another = topmarkerlist;
       !found && another != NULL;another = another->next)
  {
     if(another->high == 1) {
        found = TRUE;
        if (another->box==box) {
            ptrlist = another;
        }
        else {
           another->high = 0;
           graphBoxDraw(another->box,BLACK,WHITE);
        }
     }
  }

  if (ptrlist==NULL) {
     for(another = topmarkerlist;
       ptrlist==NULL && another != NULL;another = another->next)
     {
        if(another->box == box)
	   ptrlist = another;
     }
     if(!ptrlist){
        printf("Marker NOT FOUND\n");
        return;
     }
     if(ptrlist->high == 0){
       ptrlist->high = 1;
       graphBoxDraw(box,WHITE,BLACK);
     }
     return;
  }

  if(ptrlist->type == CLONECLASS){	  
     displayclone(ptrlist->cloneindex);
     if(graphActivate(g7)) graphPop();
     return;
  }
  if(ptrlist->type == EXPANDCONTIGS){
     displaydetailsformkr(markerdisplayed, FALSE);
     if(graphActivate(g7)) graphPop();
     return;
  }
  if(ptrlist->type == EXPANDCLONES){
     displaydetailsformkr(markerdisplayed, TRUE);
     if(graphActivate(g7)) graphPop();
     return;
  }
  if (merging) {
     printf("Cannot display another contig while merging.\n");
     return;
  }
  if (currentctg == ptrlist->cloneindex) {
     if (!trail) {
       highlightnodraw(FALSE);
       highlightmarkernodraw(FALSE);
     }
  }
  else {
    newctg = TRUE;
    /*currentctg = ptrlist->cloneindex;  fred 6/17/03*/
  }
  highmark = currentmarker = markerdisplayed;
  togglejustchanged=FALSE;
  if(displaymap){
      ptr= arrp(markerdata,currentmarker,MARKER)->pos;
      if(ptr->ctg == ptrlist->cloneindex)
         centre_pos = ptr->pos;
      else{
         found2 = FALSE;
	 ptr=ptr->next;
	 /* sness */
	 /*	 while(!found2 & ptr != NULL){ */
	 while(!found2 && (ptr != NULL)){
	   if(ptr->ctg == ptrlist->cloneindex){
	      centre_pos = ptr->pos; 
	      found2 = TRUE;
	   }
	   ptr=ptr->next;
	 }
      }
      currentclone = -1;
      centreMarker=currentmarker;
      ctgdisplay(ptrlist->cloneindex);
      /*graphPop();   fred 3/5/03 */
      gdk_window_raise(ctg_window->window);
   }
   if(graphActivate(gmarker))
      /*  graphPop();  fred 3/5/03 -- why do we need this?*/

   if(graphActivate(gtextwhole)){
      texthigh.ctg = ptrlist->cloneindex;
      updateproj();
   }
} 

/*******************************************************************
 called when a clone or contig is selcted from marker popup for clones or ctgs
*******************************************************************/
void spooky3(int box, float x, float y)
{
  struct markerdisplist *another, *ptrlist;
  struct markerctgpos *ptr;
  BOOL found=FALSE,found2;

  if(box == 0) return;

  for(ptrlist=NULL, found=FALSE, another = popupmarkerlist;
       !found && another != NULL;another = another->next)
  {
     if(another->high == 1) {
        found = TRUE;
        if (another->box==box) {
            ptrlist = another;
        }
        else {
           another->high = 0;
           graphBoxDraw(another->box,BLACK,WHITE);
        }
     }
  }

  if (ptrlist==NULL) {
     for(another = popupmarkerlist;
       ptrlist==NULL && another != NULL;another = another->next)
     {
        if(another->box == box)
	   ptrlist = another;
     }
     if(!ptrlist){
        printf("3: Marker NOT FOUND\n");
        return;
     }
     if(ptrlist->high == 0){
       ptrlist->high = 1;
       graphBoxDraw(box,WHITE,BLACK);
     }
     return;
  }

  if(ptrlist->type == CLONECLASS){	  
     displayclone(ptrlist->cloneindex);
     if(graphActivate(g7)) graphPop();
     return;
  }
  if(ptrlist->type == EXPANDCONTIGS){
     displaydetailsformkr(markerdisplayed, FALSE);
     if(graphActivate(g7)) graphPop();
     return;
  }
  if(ptrlist->type == EXPANDCLONES){
     displaydetailsformkr(markerdisplayed, TRUE);
     if(graphActivate(g7)) graphPop();
     return;
  }
  if (merging) {
     printf("3: Cannot display another contig while merging.\n");
     return;
  }
  if (currentctg == ptrlist->cloneindex) {
     if (!trail) {
       highlightnodraw(FALSE);
       highlightmarkernodraw(FALSE);
     }
  }
  else {
    newctg = TRUE;
    // currentctg = ptrlist->cloneindex;  fred 6/17/03
  }
  highmark = currentmarker = markerdisplayed;
  togglejustchanged=FALSE;
  if(displaymap){
      ptr= arrp(markerdata,currentmarker,MARKER)->pos;
      if(ptr->ctg == ptrlist->cloneindex)
         centre_pos = ptr->pos;
      else{
         found2 = FALSE;
	 ptr=ptr->next;
	 // sness
	 //	 while(!found2 & ptr != NULL){
	 while(!found2 && (ptr != NULL)){
	   if(ptr->ctg == ptrlist->cloneindex){
	      centre_pos = ptr->pos; 
	      found2 = TRUE;
	   }
	   ptr=ptr->next;
	 }
      }
      currentclone = -1;
      centreMarker=currentmarker;
      ctgdisplay(ptrlist->cloneindex);
      // graphPop();   fred 3/5/03
      gdk_window_raise(ctg_window->window);
   }
   if(graphActivate(gmarker))
      //  graphPop();  fred 3/5/03 -- why do we need this?

   if(graphActivate(gtextwhole)){
      texthigh.ctg = ptrlist->cloneindex;
      updateproj();
   }
}

void editmarkerdata()
{
  GtkWidget *window1;

  window1 = create_markerEditWindow();
  if(window1!=NULL) gtk_widget_show (window1);
}
void preserveset2()
{
  preserveit(2);
}
/**************************************************************
             DEF: addtoFp
*************************************************************/
static void AddToFp()
{
  struct markerclone *clp;
  struct marker *marker;

    marker = arrp(markerdata,markerdisplayed,MARKER);

    addfp(marker->cloneindex, 0);
    for (clp = marker->nextclone; clp != NULL; clp = clp->nextclone)
       addfp(clp->cloneindex, 0);
    drawfpdata(0);
}
/**************************************************************
             DEF: addtoGel
*************************************************************/
static void AddToGel()
{
  struct markerclone *clp;
  struct marker *marker;

    marker = arrp(markerdata,markerdisplayed,MARKER);

    addgel(marker->cloneindex, 0);
    for (clp = marker->nextclone; clp != NULL; clp = clp->nextclone)
       addgel(clp->cloneindex, 0);
}
/**************************************************************
             DEF: closeMarker
*************************************************************/
static void closeMarker() {
  if(graphActivate(gmarker)) graphDestroy(); /* marker text */
  if(graphActivate(gmarkerpopup)) graphDestroy(); /* marker text */
}

/*****************************************************************
             DEF: displaymarker
*****************************************************************/
void displaymarker(int index)
{
  struct markerctgpos *p;
  struct markerclone *clones;
  struct marker *marker;
  struct remark *pointer;  /*fred 11/1/02*/
  struct markerdisplist *another=NULL,*temp,*temp2;
  float line = 1.0;
  int i,j=-1,num=1;
  int mkrcount = 0, ctgcount = 0;
  char buf[20], str[140], str1[140]; 
  BOOL first = TRUE;
  static MENUOPT amenu[] = { 
	{ closeMarker, "Close"},
    { graphPrint,"Print Screen"},
    { AddToFp, "Add to Fp"},
    { AddToGel, "Add to Gel"},
    { 0, 0 } };

    if(index < 0) return;
    if (index >= arrayMax(markerdata))  return;
    if(active & EDITMARKER){
        displaymess("Edit window open. Please Cancel or Apply before opening a text window.");
        return;
    }

    markerdisplayed = index;
    marker = arrp(markerdata,index,MARKER);
    if(graphActivate(gmarker)){   /* set up the graph buttons, menus etc */
        graphClear();
        graphPop();
        if(preserve)
	  graphRegister(PICK, falsepick);
    }
    else{ 
        gmarker = graphCreate (TEXT_SCROLL,"Marker",.2,.2,.26,.3) ;
        graphRegister(PICK, spooky2);
    }
    graphMenu(amenu);

    /* NEED TO FREE THE OLD MARKER DATA */
    temp = topmarkerlist;
    while(temp != NULL){
      temp2 = temp;
      temp = temp->next;
      messfree(temp2);
    }

    if(!merging && !preserve)
      graphButton("Edit",editmarkerdata,0.0,0.0);
    if(!preserve)
      graphButton("Preserve",preserveset2,6.0,0.0);
    sprintf(str1,"%s %s",markertype[marker->type], marker->marker);
    line += 1.0;
    graphText(str1,1.0,line);

    /* fred 5/28/03*/
    if(marker->anchor){
      line += 2.0;
      if(marker->frame_type == FRAME) strcpy(str1,"Frame");
      else strcpy(str1,"Place");
      sprintf(str,"%s %s %s %-8.1f",Proj.label_abbrev, marker->anchor_bin, str1, marker->anchor_pos);
      graphText(str, 1.0,line);
    }

    line+=2.0;
    formatdate(&(marker->creation_date),buf);
    sprintf(str1,"Created  %s ", buf);
    graphText(str1,1.0,line++);

    formatdate(&(marker->modified_date),buf);
    sprintf(str1,"Modified %s", buf);
    graphText(str1,1.0,line++);

/* CONTIGS */

    for (p = marker->pos; p!=NULL; p = p->next) ctgcount++;
    if (ctgcount > MAX_CTGMKR_ELEMS)
    {
      i = graphBoxStart();
      line += 2.0;
      sprintf(str1, "Contigs: %d", ctgcount);
      if(!preserve)
        j = graphTextFormat(BOLD);
      graphText(str1, 1.0, line);
      if(!preserve)
        j = graphTextFormat(j);
      graphBoxEnd();
      if (first){ 
        topmarkerlist = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	topmarkerlist->cloneindex = 0;
	topmarkerlist->high = 0;
	topmarkerlist->type = EXPANDCONTIGS;
	topmarkerlist->box = i;
	topmarkerlist->next = NULL;
	another = topmarkerlist;
        first = FALSE;
      }
      else
      {
	another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	another = another->next;
	another->cloneindex = 0;
	another->high = 0;
	another->box = i;
	another->type = EXPANDCONTIGS;
	another->next = NULL;
      }
    }
    else
    {
      /* WN 4/04 moved this block in here so 'Contigs' doesn't print twice */
      if(marker->pos != NULL){
         line+=1.0;
         graphText("Contigs:",1.0,line);
         line+=1.0;
      }
      for (p = marker->pos; p!=NULL; p = p->next) 
      {
        if(p->ctg != 0){
	  i = graphBoxStart();
	  sprintf(str1," ctg%d ",p->ctg);
	  if(!preserve)
	    j = graphTextFormat(BOLD);
	  graphText(str1,1.0,line);
	  if(!preserve)
	    j = graphTextFormat(j);

	  clones = marker->nextclone;
	  num=0;
	  if(arrp(acedata,marker->cloneindex,CLONE)->ctg == p->ctg)
	    num++;
	  while(clones != NULL){
	    if(arrp(acedata,clones->cloneindex,CLONE)->ctg == p->ctg)
	      num++;
	    clones = clones->nextclone;
	  }
	
	  sprintf(str1," %d %d",num,p->pos);
	  num = 0;
	  graphText(str1,10.0,line); 
	  graphBoxEnd();
	  if(first){
	    topmarkerlist = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	    topmarkerlist->cloneindex = p->ctg;
	    topmarkerlist->high = 0;
	    topmarkerlist->type = CTGCLASS;
	    topmarkerlist->box = i;
	    topmarkerlist->next = NULL;
	    another = topmarkerlist;
	    first = FALSE;
	  }
	  else{
	    another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	    another = another->next;
	    another->cloneindex = p->ctg;
	    another->high = 0;
	    another->box = i;
	    another->type = CTGCLASS;
	    another->next = NULL;
	  }
	  line = line + 1.0;
        }
      }
    }

    /* cari 2apr04 - this is not updated everywhere, so recalc */
    marker->count=1;
    for (clones = marker->nextclone; clones != NULL; clones = clones->nextclone)
         marker->count++;
    mkrcount = marker->count;

    if (mkrcount > MAX_CTGMKR_ELEMS)
    {
      /* 1st CLONE */
      line+=2.0;
      i = graphBoxStart();
      if (!preserve)
        j = graphTextFormat(BOLD);
      sprintf(str1,"Clones: %d",marker->count);
      graphText(str1,1.0,line);
      if (!preserve)
        j = graphTextFormat(j);
      graphBoxEnd();
      line+=1.0;
      if (first){ 
        topmarkerlist = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	topmarkerlist->cloneindex = 0;
	topmarkerlist->high = 0;
	topmarkerlist->type = EXPANDCLONES;
	topmarkerlist->box = i;
	topmarkerlist->next = NULL;
	another = topmarkerlist;
        first = FALSE;
      }
      else
      {
	another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	another = another->next;
	another->cloneindex = 0;
	another->high = 0;
	another->box = i;
	another->type = EXPANDCLONES;
	another->next = NULL;
      }
    }
    else
    {
      /* 1st CLONE */
      line+=1.0;
      sprintf(str1,"Clones %d:",marker->count);
      graphText(str1,1.0,line);
      line+=1.0;

      i = graphBoxStart();
      if(!preserve)
        j = graphTextFormat(BOLD);
      graphText(arrp(acedata,marker->cloneindex,CLONE)->clone,2.0,line);
      if(!preserve) j = graphTextFormat(j);

      if(first){
        topmarkerlist = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
        topmarkerlist->cloneindex = marker->cloneindex;
        topmarkerlist->high = 0;
        topmarkerlist->box = i;
        topmarkerlist->type = CLONECLASS;
        topmarkerlist->next = NULL;
        another = topmarkerlist;
        first = FALSE;
      }
      else{
        another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
        another = another->next;
        another->cloneindex = marker->cloneindex;
        another->high = 0;
        another->box = i;
        another->type = CLONECLASS;
        another->next = NULL;
      }
      if(arrp(acedata,marker->cloneindex,CLONE)->ctg != 0)
        graphText(arrp(acedata,marker->cloneindex,CLONE)->chctg,16.0,line);
      if (IsSeq(arrp(acedata,marker->cloneindex,CLONE))) 
                 graphText("S",25.0,line);
      if (marker->weak)
                 graphText("Weak",27.0,line);
      graphBoxEnd();

      /* REST of CLONE */
      for (clones = marker->nextclone; clones != NULL; clones = clones->nextclone)
      {
        line += 1.0;
        i = graphBoxStart();
        if(!preserve)
	  j = graphTextFormat(BOLD);
        graphText(arrp(acedata,clones->cloneindex,CLONE)->clone,2.0,line);
        if(!preserve)
	  j = graphTextFormat(j);
      
        if(!preserve){
	  another->next = (struct markerdisplist *)messalloc((sizeof(struct markerdisplist)));
	  another = another->next;
	  another->cloneindex = clones->cloneindex;
	  another->high = 0;
	  another->box = i;
	  another->type = CLONECLASS;
	  another->next = NULL;
        }
        if(arrp(acedata,clones->cloneindex,CLONE)->ctg != 0)
	  graphText(arrp(acedata,clones->cloneindex,CLONE)->chctg,16.0,line);
        graphBoxEnd();
        if(IsSeq(arrp(acedata,clones->cloneindex,CLONE))) 
                graphText("S",25.0,line);
        if(clones->weak)
	        graphText("Weak",27.0,line);
      }
    }

    pointer = marker->remark;
    if(pointer!=NULL) {
      line += 2.0;
      graphText("Remarks:",1.0,line);
      line += 1.0;
    }
    while(pointer != NULL){
      graphText(pointer->message,2.0,line);
      line += 1.0;
      pointer = pointer->next;
    }

    j = graphTextFormat(PLAIN_FORMAT);

    graphText("   ",0.0,++line);
    graphTextBounds(6, line+5);

    graphRedraw();
}

void markercorrect()
{
  int max;
  int i;
  struct markerclone *newmarker;
  struct markertop *markertop;
  struct marker *marker;
  CLONE *clone;
  int index;

  max = arrayMax(acedata);

  for(i=0;i<max;i++){ /* for each clone */
    
    clone = arrp(acedata,i,CLONE);
    markertop = clone->marker;
    while(markertop != NULL){
      if(fppFind(markerdata,markertop->marker,&index, markerOrder)){
	markertop->markerindex = index;
	marker = arrp(markerdata,markertop->markerindex,MARKER);
	if(marker->cloneindex == -1)
	  marker->cloneindex = i;
	else{
	  newmarker=marker->nextclone;
	  while(newmarker->cloneindex != -1){
	    newmarker = newmarker->nextclone;
	  }
	  newmarker->cloneindex = i;
	}
      }
      else
	printf("FPC ERROR could not find marker %s (in markercorrect)\n",markertop->marker);
      markertop = markertop->nextmarker;

    }
  } /* end for */
}

/*********************************************************
              DEF: updatemarkerpos
**********************************************************/
void updatemarkerpos(int distance)
{
  struct markerctgpos *pos;
  struct marker *marker;
  struct markerlist *p2;
  BOOL sort=FALSE;
  int l, found;

/* find all clones for marker that need updating*/
  for(l=0;l<arrayMax(markerdata);l++)
  {
    marker = arrp(markerdata,l,MARKER);
    pos = marker->pos;
    while(pos != NULL){
      if(pos->status == USERUPDATE)
	pos->status = USER;
      if(pos->status == AUTOUPDATE){
	pos->status = AUTO;
	pos->pos = calcmarkerctgpos(pos,l);
	p2=markerlistroot;
	found = FALSE;
	while(p2 != NULL && !found){
	  if(p2->markerindex == l){
	    found = TRUE;
	    sort = TRUE;
	    p2->midpt = pos->pos;
	  }
	  p2=p2->next;
	}
      }
      pos = pos->next; 
    }
    markersinctgcount();
    if(sort)
      sortmarkers();
  }
}

/*********************************************************
              DEF: updatemarkerpos2
**********************************************************/
void updatemarkerpos2(int distance)
{
  struct markerctgpos *pos;
  struct marker *marker;
  struct markerlist *mp;
  BOOL sort=FALSE;

/* find all clones for marker that need updating*/
  mp = markerlistroot;
  while(mp !=NULL){
    marker = arrp(markerdata,mp->markerindex,MARKER);
    pos = marker->pos;
    while(pos != NULL){
      if(pos->status == USERUPDATE)
	pos->status = USER;
      if(pos->status == AUTOUPDATE){
	pos->status = AUTO;
	sort=TRUE;
	pos->pos = calcmarkerctgpos(pos,mp->markerindex);
	mp->midpt = pos->pos;
      }
      pos = pos->next; 
    }
    mp = mp->next;
  }
    if(sort)
      sortmarkers();
}

/*****************************************************************
                   DEF: sortmarkers
**************************************************************/
void sortmarkers()
{
  struct markerlist *p,*p2;
  int done=0, temp,temp2;
  int m1mid,m2mid;
   
  while(!done) {
    done=1;
    p=p2=markerlistroot;
    while(p != NULL && p2 != NULL){
      p2 = p->next;
      if(p2!=NULL){
	m1mid = p->midpt;
	m2mid = p2->midpt;
	if(m2mid < m1mid){
          done=0;
	  temp = p2->markerindex;
	  temp2 = p2->midpt;
	  p2->markerindex = p->markerindex;
	  p2->midpt = p->midpt;
	  p->markerindex = temp;
	  p->midpt = temp2;
	}
      }
      p = p2;
    }
  }
}

/*****************************************************************
                   DEF: setmarkerposctg
**************************************************************/
void setmarkerposctg()
{

  struct marker *tmp;
  struct markerctgpos *p2;
  struct markerlist *markerptr=NULL;
  BOOL first = TRUE,added;
  int l;

  Nmarkers = 0;
  if (markerlistroot!=NULL) quitMark();

  for(l=0;l<arrayMax(markerdata);l++){
    tmp = arrp(markerdata,l,MARKER);
    tmp->box = 0;
    tmp->colour = 0;
      p2=tmp->pos;
      added = FALSE;
      while(p2!=NULL && !added){
	if(p2->ctg == currentctg){
	  if(first){
	    markerlistroot = (struct markerlist *)
	      messalloc((sizeof(struct markerlist)));	
	    markerlistroot->markerindex = l;
	    markerlistroot->next = NULL;
	    markerptr = markerlistroot;
	    markerlistroot->midpt = p2->pos;
	    first = FALSE;
            added = TRUE;
	    Nmarkers = 1;
	  }
	  else{
	    markerptr->next =  (struct markerlist *)
	      messalloc((sizeof(struct markerlist)));	
	    markerptr = markerptr->next;
	    markerptr->markerindex = l;
	    markerptr->next = NULL;
	    markerptr->midpt = p2->pos;
	    Nmarkers++;
            added = TRUE;
	  }
	}
	p2 = p2->next;
      }
    }
}

/* Added by WN */
/* figure out the max number of clones attached to a marker */
/* this has to be called before blocks which rely on Marker_clone_max
    (actually only calcmarkerctgpos it appears) */ 
void set_marker_clone_max()
{
    MARKER* mrk;
    int max = 0;
    int i;
    int count;
    struct markerclone* nextclone;

    for (i = 0; i < arrayMax(markerdata); i++)
    {
        mrk = arrp(markerdata, i, MARKER);
        count = 0;
        if (mrk->cloneindex > -1)
        {
            count = 1;
            nextclone = mrk->nextclone;
            while (nextclone)
            {
                count++;
                nextclone = nextclone->nextclone;
            }
        }
        if (count > max)
        {
            max = count;
        }
    }
    max++; /* for good measure */
    Marker_clone_max = max;
}

/*****************************************************************
                  DEF: calcmarkerctgpos
****************************************************************/
int calcmarkerctgpos(struct markerctgpos *pos,int markerindex)
{
  struct markerclone *p;
  struct marker *marker;
  CLONE *clone;
  struct posman {
      int left, right, ctg;
  } *pt, tmp;
  int *stack, s;
  int k, depth, npt, i, j;
  int x=0, y=0, save_depth;
  int position;

  set_marker_clone_max(); /* WN 6/24/04 */
  
  pt = (struct posman *) calloc(Marker_clone_max, sizeof(struct posman));
  stack = (int *) calloc(Marker_clone_max, sizeof(int));
  if (pt==NULL || stack == NULL) {
     printf("Memory error in calcctgpos\n"); exit(0);
  }
  for (i=0;i<Marker_clone_max; i++) stack[i]=-1;
  marker = arrp(markerdata,markerindex,MARKER);
  npt = 0;
  clone = arrp(acedata,marker->cloneindex,CLONE);
  p = marker->nextclone;
  if(clone->ctg == pos->ctg){
    pt[npt].ctg = clone->ctg;
    pt[npt].left = clone->x;
    pt[npt].right = clone->y;
    npt++;
  }
  while(p!= NULL){
    clone = arrp(acedata,p->cloneindex,CLONE);
    if(clone->ctg ==  pos->ctg){
      pt[npt].ctg = clone->ctg;
      pt[npt].left = clone->x;
      pt[npt].right = clone->y;
      npt++;
    }
    p = p->nextclone;
  }
  if (npt == 0) { 
      fprintf(stderr,"Zero clones in contig %d for marker %s\n",pos->ctg,marker->marker); 
      return 0;
  }
  for (i=0; i<npt-1; i++)
    for (j=i+1; j<npt; j++) 
      if (pt[i].left > pt[j].left) {
	tmp = pt[i];
	pt[i] = pt[j];
	pt[j] = tmp;
      }
  x = pt[0].left;
  y = pt[0].right;
  stack[0] = y;
  /* sness */
  /*position = x+y >> 1; */
  position = (x+y) >> 1;
  depth = save_depth = 1;
  for(i=1; i<npt;i++){
    if (pt[i].left <= y) {
      if (depth == Marker_clone_max) { 
           fprintf(stderr,"Went passed marker limit of %d\n", Marker_clone_max); exit(0);}
      stack[depth++] = pt[i].right;
      x = MaX(x, pt[i].left);
      y = MiN(y, pt[i].right);
    }
    else {
      if (depth > save_depth) {
	save_depth = depth;
	/* sness */
	/*position = x+y >> 1; */
	position = (x+y) >> 1;
      }
      x = pt[i].left;
      y = pt[i].right;
      stack[depth++] = y;
      for (j=-1, k=s=0; s< depth; s++) 
	{
	  if (stack[s] < x) {
	    stack[s] = -1;
	    if (j == -1) j = s;
	  }
	  else { 
	    k++;
	    y = MiN(y, stack[s]);
	    if (j!=-1 && stack[j]== -1) { /* 14may99 purify uninit mem FIX */
	      stack[j] = stack[s];
	      stack[s] = -1;
	      while (stack[j]!=-1) j++;
	    } else j = s;
	  }
	}
      depth=k;
    }
  }
  if (depth > save_depth) {
	/* sness */
    /* position = x+y >> 1; */
    position = (x+y) >> 1;
  }
  free(pt); free(stack);
  return position;
}
